<template>
  <div>
    <!--顶部操作栏-->
    <a-button-group>
      <a-button @click='showAddFile = true'>
        <a-icon type='upload' />
        上传文件/文件夹
      </a-button>
      <a-button icon='plus' @click='makeDir.showMakeDir = true'>新建文件夹</a-button>
      <a-button @click='showDeleteConfirm'>
        <a-icon type='rest' />
        批量删除
      </a-button>
      <a-button @click='downloadFiles'>
        <a-icon type='vertical-align-bottom' />
        批量下载
      </a-button>
      <a-button>
        <a-icon type='share-alt' />
        批量分享
      </a-button>
    </a-button-group>
    
    <a-input-search
      v-model='searchValue'
      placeholder='搜索当前目录下的文件'
      style='width: 20%;margin-left: 20px;'>
    </a-input-search>
    
    <a-card style='margin-top: 20px;'>
      <!--面包屑导航栏-->
      <a-breadcrumb>
        <a-breadcrumb-item class='breadcrumb-path'>
          <span class='breadcrumb-path' @click='() => {curPath = "/";getFileData()}'>根目录</span>
        </a-breadcrumb-item>
        <a-breadcrumb-item
          v-for='item in breadcrumb'>
          <span class='breadcrumb-path' @click='goBreadcrumb(item)'>{{ item.path }}</span>
        </a-breadcrumb-item>
      </a-breadcrumb>
      
      <!--文件列表-->
      <a-table
        style='margin-top: 20px;'
        :row-selection='{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }'
        row-key='fileName'
        :columns='columns'
        :loading='tbLoading'
        :data-source='filteredItems'
      >
        <!--文件名-->
        <div
          slot='fileName'
          style='cursor: pointer;'
          slot-scope='text, record'>
          <div @click='changeDirOrPreviewFile(record)'>
            <img style='width: 35px;height: 35px;'
                 :src='getFileIcon(record.extension)'
                 :alt='record.extension' />
            <span style='margin-left: 10px;'>{{ text }}</span>
          </div>
        </div>
        
        <!--文件类型-->
        <div
          slot='extension'
          slot-scope='text, record'>
          {{ text === 'dir' ? '文件夹' : text }}
        </div>
        
        <!--创建人-->
        <div
          slot='author'
          slot-scope='text, record'>
          <a-tag v-if='text !== null' color='purple' style='border-radius: 5px'>{{ text }}</a-tag>
          <span v-else>- - - -</span>
        </div>
        
        <!--文件大小-->
        <div
          slot='size'
          slot-scope='text, record'>
          {{ text !== 0 ? formatBytesWithThresholds(text) : '- - - -' }}
        </div>
        
        <!--更新时间-->
        <div
          slot='updateTime'
          slot-scope='text, record'>
          {{ text !== null ? text : '- - - -' }}
        </div>
        
        <!--操作-->
        <div
          slot='action'
          slot-scope='text, record'>
          <a-space>
            <a-button style='border-radius: 7px' v-if='!record.isDir' @click='downloadFile(record)'>下载</a-button>
            <a-button type='primary'
                      style='border-radius: 7px;'
                      :style='record.isDir ? {marginLeft: "72px"} : ""'
                      @click='deleteFile(record.fileName)'>删除
            </a-button>
          </a-space>
        </div>
      
      </a-table>
    </a-card>
    
    <!--文件预览弹窗-->
    <a-modal
      title='文件预览'
      width='90vw'
      :dialog-style="{ top: '20px' }"
      :visible='previewFile.show'
      @ok='() => {previewFile.show=false;previewFile.id=""}'
      @cancel='() => {previewFile.show=false;previewFile.id=""}'
    >
      <MarkDownPreview v-if='previewFile.id === "MD"' :url='previewFile.url' />
      <VideoPreview v-if='previewFile.id === "VIDEO"' :src='previewFile.url' />
      <CodePreview v-if='previewFile.id === "CODE"' :url='previewFile.url' />
      <PdfPreview v-if='previewFile.id === "PDF"' :url='previewFile.url' />
      <WordPreview v-if='previewFile.id === "WORD"' :url='previewFile.url' />
    </a-modal>
    
    <!--新建文件夹-->
    <a-modal
      title='新建文件夹'
      :visible='makeDir.showMakeDir'
      @ok='handleMakeDir'
      @cancel='() => {makeDir.showMakeDir=false}'
    >
      <a-row type='flex' justify='space-around' align='middle'>
        <a-col span='8'>
          <img src='/fileIcon/makeDir.png' alt='makeDir' style='margin-left: 50px;' />
        </a-col>
        <a-col span='10'>
          <a-input placeholder='文件夹名称' v-model='makeDir.dirName' />
        </a-col>
      </a-row>
    </a-modal>
    
    <!--上传文件-->
    <a-modal
      title='上传文件或者文件夹 (支持秒传、断点续传和分片上传)'
      :visible='showAddFile'
      @ok='() => {handleUpload()}'
      @cancel='() => {showAddFile=false}'
      ok-text='开始上传'
      cancel-text='取消上传'
      width='50vw'
      style='display: block'
    >
      <FileUpload
        ref='fileUpload'
        @onChangeModelStatus='onChangeModelStatus'
        :cur-path='curPath' />
    </a-modal>
  
  </div>
</template>

<script>
import { delDirOrFiles, getQuestionBank, makeFolder } from '@/api/adminTopic'
import MarkDownPreview from '@/views/questionBank/preview/markDownPreview.vue'
import axios from 'axios'
import FileSaver from 'file-saver'
import VideoPreview from '@/views/questionBank/preview/videoPreview.vue'
import CodePreview from '@/views/questionBank/preview/codePreview.vue'
import FileUpload from '@/views/questionBank/upload/FileUpload.vue'
import PdfPreview from '@/views/questionBank/preview/pdfPreview.vue'
import WordPreview from '@/views/questionBank/preview/wordPreview.vue'

const columns = [
  {
    title: '文件名',
    dataIndex: 'fileName',
    scopedSlots: { customRender: 'fileName' }
  },
  {
    title: '类型',
    dataIndex: 'extension',
    scopedSlots: { customRender: 'extension' }
  },
  {
    title: '大小',
    dataIndex: 'size',
    scopedSlots: { customRender: 'size' }
  },
  {
    title: '创建人',
    dataIndex: 'author',
    scopedSlots: { customRender: 'author' }
  },
  {
    title: '修改时间',
    dataIndex: 'updateTime',
    scopedSlots: { customRender: 'updateTime' }
  },
  {
    title: '操作',
    dataIndex: 'action',
    scopedSlots: { customRender: 'action' },
    fixed: 'right',
    width: 200
  }
]
export default {
  name: 'index',
  components: {
    WordPreview,
    PdfPreview,
    CodePreview,
    VideoPreview,
    MarkDownPreview,
    FileUpload
  },
  data() {
    return {
      columns,
      tbLoading: false,
      // 上传的文件列表
      fileList: [],
      // 被选择的值
      selectedRowKeys: [],
      searchValue: '',
      // 当前文件路径
      curPath: '/',
      // 文件信息
      tbInfo: [],
      // 面包屑导航栏
      breadcrumb: [],
      previewFile: {
        id: '',
        title: '',
        show: false,
        url: ''
      },
      showAddFile: false,
      makeDir: {
        showMakeDir: false,
        dirName: ''
      }
    }
  },
  created() {
    this.getFileData()
  },
  computed: {
    filteredItems() {
      return this.tbInfo.filter(item =>
        item.fileName.toLowerCase().includes(this.searchValue.toLowerCase())
      )
    }
  },
  methods: {
    onSelectChange(selectedRowKeys) {
      this.selectedRowKeys = selectedRowKeys
    },
    handleMakeDir() {
      if (this.makeDir.dirName === '') {
        this.$message.error('文件夹名称不能为空')
        return
      }
      const specialCharacters = [' ', '\\', '/', ':', '*', '?', '"', '<', '>', '|']
      if (specialCharacters.some(char => this.makeDir.dirName.includes(char))) {
        this.$message.error(`文件夹名 "${this.makeDir.dirName}" 不正确。文件夹名不能包含下列任何字符: \ / : * ? " < > | `)
        return
      }
      makeFolder(this.makeDir.dirName, this.curPath).then(() => {
        this.$message.success('创建文件夹成功')
        this.getFileData()
      })
      // 获取当前路径
      this.makeDir.dirName = ''
      this.makeDir.showMakeDir = false
    },
    showDeleteConfirm() {
      let _this = this
      if (_this.selectedRowKeys.length === 0) {
        this.$message.error('请选择要删除的文件或文件夹')
        return
      }
      // 构造被删除的文件名
      const h = this.$createElement
      let contentNodes = []
      _this.selectedRowKeys.forEach((item, index) => {
        contentNodes.push(h('p', (index + 1) + '. ' + item))
      })
      this.$confirm({
        title: '确认删除文件夹或文件夹?',
        content: h('div',
          {
            style: {
              padding: '0',
              margin: '0'
            }
          },
          contentNodes),
        okText: '确认',
        okType: 'danger',
        cancelText: '取消',
        onOk() {
          // 批量删除
          delDirOrFiles(_this.selectedRowKeys).then(() => {
            _this.$message.success('删除成功')
            _this.selectedRowKeys = []
            _this.getFileData()
          })
        },
        onCancel() {
        
        }
      })
    },
    // 文件下载
    downloadFile(record) {
      if (record.isDir) {
        this.$message.error('暂不支持文件夹下载')
        return
      }
      let fileName = record.fileName
      let dwUrl = 'http://10.226.8.14:9000/jx-welcome-minio/' + fileName
      axios.get(dwUrl, { responseType: 'arraybuffer' })
        .then(res => {
          let blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' })
          FileSaver.saveAs(blob, fileName)
          this.$notification['success']({
            message: '下载成功',
            description:
              '文件名：' + fileName
          })
        })
    },
    deleteFile(fileName) {
      let _this = this
      let files = [fileName]
      const h = this.$createElement
      this.$confirm({
        title: '确认删除文件夹或文件夹?',
        content: h('div',
          {
            style: {
              padding: '0',
              margin: '0'
            }
          },
          files),
        okText: '确认',
        okType: 'danger',
        cancelText: '取消',
        onOk() {
          // 批量删除
          delDirOrFiles(files).then(() => {
            _this.$message.success('删除成功')
            _this.selectedRowKeys = []
            _this.getFileData()
          })
        },
        onCancel() {
        
        }
      })
    },
    // 批量下载
    downloadFiles() {
      if (this.selectedRowKeys.length === 0) {
        this.$message.error('请选择要下载的文件或文件夹')
        return
      }
      this.selectedRowKeys.forEach((item) => {
        this.downloadFile({
          isDir: false,
          fileName: item
        })
      })
      // 构造被删除的文件名
      const h = this.$createElement
      let contentNodes = []
      
      this.selectedRowKeys.forEach((item, index) => {
        contentNodes.push(h('p', (index + 1) + ': ' + item))
      })
      
      this.$notification['success']({
        message: '下载成功',
        description:
          h('div',
            {
              style: {
                padding: '0',
                margin: '0'
              }
            },
            contentNodes
          )
      })
    },
    
    getFileIcon(ext) {
      const iconMap = {
        'md': '/fileIcon/md.png',
        'dir': '/fileIcon/dir.png',
        'pdf': '/fileIcon/pdf.png',
        'doc': '/fileIcon/word.png',
        'docx': '/fileIcon/word.png',
        'png': '/fileIcon/img.png',
        'jpg': '/fileIcon/img.png',
        'jpeg': '/fileIcon/img.png',
        'mp3': '/fileIcon/video.png',
        'mp4': '/fileIcon/video.png',
        'java': '/fileIcon/code.png',
        'py': '/fileIcon/code.png',
        'c': '/fileIcon/code.png',
        'cpp': '/fileIcon/code.png',
        'html': '/fileIcon/code.png',
        'css': '/fileIcon/code.png',
        'js': '/fileIcon/code.png'
      }
      if (iconMap[ext]) {
        return iconMap[ext]
      }
      return '/fileIcon/unknownFile.png'
    },
    changeDirOrPreviewFile(fileInfo) {
      // 如果是文件夹则进入文件夹
      if (fileInfo.isDir) {
        this.curPath = fileInfo.fileName
        this.getFileData()
      }
      let fileExt = fileInfo.extension
      // 图片预览
      if (fileExt === 'jpg' || fileExt === 'png' || fileExt === 'jpeg') {
        // 判断图片数量和当前图片的索引
        let imgList = []
        let nowImgIndex = 0
        let basePath = 'http://10.226.8.14:9000/jx-welcome-minio/'
        let index = 0
        this.tbInfo.forEach((item) => {
          if (item.extension === 'jpg' || item.extension === 'png' || item.extension === 'jpeg') {
            imgList.push(basePath + item.fileName)
            if (item.fileName === fileInfo.fileName) {
              nowImgIndex = index
            }
            index++
          }
        })
        this.$hevueImgPreview({ multiple: true, nowImgIndex, imgList })
      }
      // MD文件预览
      if (fileExt === 'md' || fileExt === 'txt') {
        this.previewFile.id = 'MD'
        this.previewFile.show = true
        this.previewFile.url = `http://10.226.8.14:9000/jx-welcome-minio/${fileInfo.fileName}`
      }
      
      // PDF文件预览
      if (fileExt === 'pdf') {
        this.previewFile.id = 'PDF'
        this.previewFile.show = true
        this.previewFile.url = `http://10.226.8.14:9000/jx-welcome-minio/${fileInfo.fileName}`
      }
      
      // word文件预览
      if (fileExt === 'doc' || fileExt === 'docx') {
        this.previewFile.id = 'WORD'
        this.previewFile.show = true
        this.previewFile.url = `http://10.226.8.14:9000/jx-welcome-minio/${fileInfo.fileName}`
      }
      
      // 代码预览
      if (fileExt === 'py' || fileExt === 'java' || fileExt === 'c' || fileExt === 'cpp' || fileExt === 'js' || fileExt === 'css' || fileExt === 'html') {
        this.previewFile.url = `http://10.226.8.14:9000/jx-welcome-minio/${fileInfo.fileName}`
        this.previewFile.show = true
        this.previewFile.id = 'CODE'
      }
      
      // 视频文件预览
      if (fileExt === 'mp3' || fileExt === 'mp4') {
        this.previewFile.id = 'VIDEO'
        this.previewFile.show = true
        this.previewFile.url = `http://10.226.8.14:9000/jx-welcome-minio/${fileInfo.fileName}`
      }
      
    },
    getFileData() {
      this.tbLoading = true
      getQuestionBank(this.curPath).then(res => {
        this.tbInfo = res.data.fileInfoList
        this.breadcrumb = res.data.breadcrumb
        this.tbLoading = false
      })
    },
    formatBytesWithThresholds(bytes) {
      bytes = parseInt(bytes)
      if (bytes === 0) return '0 B'
      let thresholds = {
        'K': 1024, // 1KB
        'M': 1048576, // 1024KB = 1MB
        'G': 1073741824 // 1024MB = 1GB
      }
      
      let result
      if (bytes >= thresholds['G']) {
        result = (bytes / thresholds['G']).toFixed(1) + ' GB'
      } else if (bytes >= thresholds['M']) {
        result = (bytes / thresholds['M']).toFixed(1) + ' MB'
      } else if (bytes >= thresholds['K']) {
        result = (bytes / thresholds['K']).toFixed(1) + ' KB'
      } else {
        result = bytes + ' B'
      }
      
      return result
    },
    handleUpload() {
      // 上传文件
      this.$refs.fileUpload.onFileUpload()
    },
    onChangeModelStatus(val) {
      // 重新获取文件列表
      this.showAddFile = val
      setTimeout(() => {
        this.getFileData()
      }, 1000)
    },
    handleRemove(file) {
      const index = this.fileList.indexOf(file)
      const newFileList = this.fileList.slice()
      newFileList.splice(index, 1)
      this.fileList = newFileList
    },
    beforeUpload(file) {
      this.fileList = [...this.fileList, file]
      return false
    },
    goBreadcrumb(pathInfo) {
      let index = pathInfo.index
      // 将当前索引前面的路径拼接
      let path = ''
      for (let i = 0; i < index + 1; i++) {
        path += this.breadcrumb[i].path + '/'
      }
      getQuestionBank(path).then(res => {
        this.tbInfo = res.data.fileInfoList
        this.breadcrumb = res.data.breadcrumb
      })
    }
  }
}
</script>

<style scoped>
.breadcrumb-path {
  cursor: pointer;
  font-size: 20px;
}

.breadcrumb-path:hover {
  color: #00A0E9;
}

</style>